<template>
    <div class="el-transfer">
        <transfer-panel
        v-bind="$props"
        :customFilter='leftcustomFilter'
        ref="leftPanel"
        class="left-panel"
        :data="sourceData"
        :loadDataNum="loadDataNum"
        :title="titles[0] || '列表 1'"
        :default-checked="leftDefaultChecked"
        :placeholder="filterPlaceholder || '请输入搜索内容'"
        @checked-change="onSourceCheckedChange">
        <slot name="left-footer"></slot>
        <template v-slot:leftCustomFilter>
          <slot name="leftCustomFilter"></slot>
        </template>
        </transfer-panel>
        <div class="el-transfer__buttons" :class="buttonsClass">
        <el-button
            type="primary"
            :class="['el-transfer__button', hasButtonTexts ? 'is-with-texts' : '']"
            @click.native="addToLeft"
            :disabled="rightChecked.length === 0">
            <i class="el-icon-arrow-left"></i>
            <span v-if="buttonTexts[0] !== undefined">{{ buttonTexts[0] }}</span>
        </el-button>
        <el-button
            type="primary"
            :class="['el-transfer__button', hasButtonTexts ? 'is-with-texts' : '']"
            @click.native="addToRight"
            :disabled="leftChecked.length === 0">
            <span v-if="buttonTexts[1] !== undefined">{{ buttonTexts[1] }}</span>
            <i class="el-icon-arrow-right"></i>
        </el-button>
        </div>
        <transfer-panel
        v-bind="$props"
        :customFilter='false'
        ref="rightPanel"
        :data="targetData"
        :loadDataNum="loadDataNum"
        :title="titles[1] || '列表 2'"
        :default-checked="rightDefaultChecked"
        :placeholder="filterPlaceholder || '请输入搜索内容'"
        @checked-change="onTargetCheckedChange">
        <slot name="right-footer"></slot>
        </transfer-panel>
    </div>
</template>

<script lang="ts">
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
import TransferPanel from './transfer-panel.vue'
@Component({
  name: 'V7Transfer',
  components: {
    TransferPanel
  }
})
export default class V7Transfer extends Vue {
  @Prop({ default: () => [] }) private data?: any
  @Prop({ default: () => [] }) private titles?: any
  @Prop({ default: () => [] }) private buttonTexts?: any
  @Prop({ default: () => '' }) private filterPlaceholder?: any
  @Prop() private filterMethod?: any
  @Prop() private customFilterMethod?: any
  @Prop({ default: () => ({}) }) private leftcustomFilterData?: any
  @Prop({ default: () => [] }) private leftDefaultChecked?: any
  @Prop({ default: () => [] }) private rightDefaultChecked?: any
  @Prop() private renderContent?: any
  @Prop({ default: () => [] }) private value?: any
  @Prop({ default: () => [] }) private format?: any
  @Prop(Boolean) public filterable: boolean|undefined
  @Prop(Boolean) public leftcustomFilter: boolean|undefined
  @Prop({ default: () => ({ label: 'label', key: 'key', disabled: 'disabled' }) }) private props?: any
  @Prop({ default: () => 'original' }) private targetOrder?: any
  @Prop({ default: () => 20 }) private loadDataNum?: number
  @Prop({ default: () => '' }) private buttonsClass?: string

  private leftChecked: any = []
  private rightChecked: any = []
  private allDataObj: any = {}

  get dataObj () {
    const key = this.props.key;
    return this.data.reduce((o: any, cur: any) => (o[cur[key]] = cur) && o, {});
  }

  get sourceData () {
    return this.data.filter((item: any) => this.value.indexOf(item[this.props.key]) === -1);
  }

  get targetData () {
    if (this.targetOrder === 'original') {
      if (!Object.keys(this.allDataObj).length) {
        this.handleData()
      }
      const targetArr: any = []
      this.value.forEach(item => {
        if (this.allDataObj[item]) {
          targetArr.push(this.allDataObj[item])
        }
      })
      return targetArr
    } else {
      return this.value.reduce((arr: any, cur: any) => {
        const val = this.dataObj[cur];
        if (val) {
          arr.push(val);
        }
        return arr;
      }, []);
    }
  }

  get hasButtonTexts () {
    return this.buttonTexts.length === 2;
  }

  @Watch('value')
  private valueChange (val: any) {
    this.dispatch('ElFormItem', 'el.form.change', val)
  }

  private handleData () {
    this.data.forEach(item => {
      this.allDataObj[item[this.props.key]] = item
    })
  }

  private getMigratingConfig () {
    return {
      props: {
        'footer-format': 'footer-format is renamed to format.'
      }
    };
  }

  private onSourceCheckedChange (val: any, movedKeys: any) {
    this.leftChecked = val;
    if (movedKeys === undefined) {
      return
    };
    this.$emit('left-check-change', val, movedKeys);
  }

  private onTargetCheckedChange (val: any, movedKeys: any) {
    this.rightChecked = val;
    if (movedKeys === undefined) {
      return
    };
    this.$emit('right-check-change', val, movedKeys);
  }

  private addToLeft () {
    const currentValue = this.value.slice();
    this.rightChecked.forEach((item: any) => {
      const index = currentValue.indexOf(item);
      if (index > -1) {
        currentValue.splice(index, 1);
      }
    });
    this.$emit('input', currentValue);
    this.$emit('change', currentValue, 'left', this.rightChecked);
  }

  private addToRight () {
    let currentValue = this.value.slice();
    const itemsToBeMoved: any = [];
    const key = this.props.key;
    const leftCheckedKeyPropsObj: any = {};
    this.leftChecked.forEach((item: any) => {
      leftCheckedKeyPropsObj[item] = true;
    });
    const valueKeyPropsObj: any = {};
    this.value.forEach((item: any) => {
      valueKeyPropsObj[item] = true;
    });
    this.data.forEach((item: any) => {
      const itemKey = item[key];
      if (leftCheckedKeyPropsObj[itemKey] && !valueKeyPropsObj[itemKey]) {
        itemsToBeMoved.push(itemKey);
      }
    });
    currentValue = this.targetOrder === 'unshift' ? itemsToBeMoved.concat(currentValue) : currentValue.concat(itemsToBeMoved);
    this.$emit('input', currentValue);
    this.$emit('change', currentValue, 'right', this.leftChecked);
  }

  private clearQuery (which: any) {
    if (which === 'left') {
      (this.$refs.leftPanel as any).query = '';
    } else if (which === 'right') {
      (this.$refs.leftPanel as any).query = '';
    }
  }

  private dispatch (componentName: any, eventName: any, params: any) {
    let parent: any = this.$parent || this.$root;
    let name = parent.$options.componentName;
    while (parent && (!name || name !== componentName)) {
      parent = parent.$parent;
      if (parent) {
        name = parent.$options.componentName;
      }
    }
    if (parent) {
      parent.$emit.apply(parent, [eventName].concat(params));
    }
  }
}
</script>
<style lang="stylus" scoped>
.el-transfer__button
  display block
.el-button+.el-button
  margin-left 0px
.el-button [class*=el-icon-]+span
  margin-left 0px
.el-transfer-panel
  width 300px
  .el-transfer-panel__header .el-checkbox .el-checkbox__label
    font-size 14px
  .el-form-item__label
    color #767e92
    font-size 12px
  .el-transfer-panel__item
    margin 10px 10px 10px 0px
  .el-transfer-panel__item.el-checkbox .el-checkbox__label
    font-size 12px
  .el-transfer__button i, .el-transfer__button span
    font-size 12px
.el-tabs__nav-wrap::after
  //display none
>>> .el-transfer-panel__filter .el-input__inner
  padding-right 30px
  padding-left 20px
>>> .el-input__prefix
  left 235px
</style>
